/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.sais.eswn.core;

import java.awt.Color;
import java.io.BufferedWriter;
import java.io.File;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.SocketException;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import org.sais.eswn.card.CardSet;
import org.sais.eswn.deck.Deck;
import org.sais.eswn.deck.decFilter;
import org.sais.eswn.net.ClientSock;
import org.sais.eswn.net.HostSock;
import org.sais.eswn.net.Sock;
import org.sais.eswn.tool.Tools;
import org.sais.eswn.ui.GamePlayFrame;

/**
 *
 * @author Romulus
 */
public class GameCore {

    public final static String sVersion = "build-11";
    public final static String sTitle = "東方銀翼札";
    public final static String sDisplayTitle = sTitle + " " + sVersion;
    public static final int REGION_DECK = 0;
    public static final int REGION_FIELD = 1;
    public static final int REGION_GRAVE = 2;
    public static final int REGION_PLAY_SPELL = 3;
    public static final int REGION_PLAY_EVENT = 4;
    public static final int REGION_OPP_DECK = 5;
    public static final int REGION_OPP_FIELD = 6;
    public static final int REGION_OPP_GRAVE = 7;
    public static final int PHASE_TACTICS = 0;
    public static final int PHASE_BATTLE = 1;
    private IGameInterface mUI;
    private boolean mIsWatcher;
    private Player[] mPlayers = new Player[]{new Player(), new Player()};
    private int mPhase = PHASE_TACTICS;
    private boolean isHost;
    private Sock mSock = null;
    private BufferedWriter out;
    private boolean isCardSet;

    // Startup sequence
    public static GameCore startPlay(Socket soc, ClientSock clisoc, boolean isHost) {
        GameCore core = new GameCore();
        IGameInterface ui = new GamePlayFrame(core);
        core.setParameters(ui, soc, clisoc, isHost);
        return core;
    }

    public static GameCore startPlay(Socket soc, HostSock hostsoc, boolean isHost) {
        GameCore core = new GameCore();
        IGameInterface ui = new GamePlayFrame(core);
        core.setParameters(ui, soc, hostsoc, isHost);
        return core;
    }

    public void setParameters(IGameInterface ui, Socket soc, ClientSock clisoc, boolean isHost) {
        mUI = ui;
        mSock = clisoc;
        this.isHost = isHost;
        this.mIsWatcher = clisoc.isWatcher();
    }

    public void setParameters(IGameInterface ui, Socket soc, HostSock hostsoc, boolean isHost) {
        mUI = ui;
        mSock = hostsoc;
        this.isHost = isHost;
    }

    //End of startup sequence

    // Game initilizing
    public void setPlayerName(int playerIndex, String name) {
        mPlayers[playerIndex].setName(name);
        mUI.setPlayerName(playerIndex, name);
    }

    // End of initilizing
    public void loadDeck(int playerIndex) {
        JFileChooser chooser = new JFileChooser();
        File f;
        String sdir = Tools.readConfig("lastdeckfolder");
        if (sdir.equals("")) {
            sdir = "deck";
        }
        if (new File(sdir).exists()) {
            f = new File(sdir);
        } else {
            f = new File(".");
        }
        chooser.setCurrentDirectory(f);
        chooser.setAcceptAllFileFilterUsed(true);
        chooser.addChoosableFileFilter(new decFilter());

        int result = chooser.showOpenDialog(null);
        if (result == JFileChooser.CANCEL_OPTION) {
            return;
        }
        try {
            File file = chooser.getSelectedFile();
            Tools.updateConfig("lastdeckfolder", file.getParent());
            Deck deck = Deck.load(file);
            mPlayers[playerIndex].setDeck(deck);
            mUI.setDeck(playerIndex, mPlayers[playerIndex].getName(), mPlayers[playerIndex].getInitialDeck());
            send("$DECKNAME:" + deck.getDeckname());
            send("$DECK:" + deck.listCardnosForSock());
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, Tools.getLoc(10));
        }
    }

    public void setDeckName(int playerIndex, String deckName) {
        mPlayers[playerIndex].getInitialDeck().setDeckname(deckName);
    }

    public void setDeckBySockString(int playerIndex, String deckString) {
        String deckname = mPlayers[playerIndex].getInitialDeck().getDeckname();
        Deck deck = new Deck();
        deck.setDeckname(deckname);
        for (String s : deckString.split(" ")) {
            deck.add(s);
        }
        mPlayers[playerIndex].setDeck(deck);
        mUI.setDeck(playerIndex, mPlayers[playerIndex].getName(), mPlayers[playerIndex].getInitialDeck());
    }

    public void setCardSet(boolean iscardset) {
        isCardSet = iscardset;
    }

    public void setPlay(int playerIndex, boolean sendMessage) {
        if (isWatcher()) {
            return;
        }
        if (isCardSet) {
            mUI.play(playerIndex);
            if (sendMessage) {
                send("$PLAY:");
            }
        } else {
            insertMessage(Tools.getLoc(22), Color.BLACK);
            send("$CARDSET:");
        }
    }

    public boolean isWatcher() {
        return mIsWatcher;
    }

    public void move(int source, int destination, String cardno, int playerIndex) {
        mPlayers[playerIndex].moveCard(source, destination, cardno);
        if (playerIndex == Player.ICH) {
            send("$MOVE:" + source + " " + destination + " " + cardno);
        }
    }

    public void updateUI(int playerIndex) {
        mUI.update(playerIndex);
    }

    public CardSet getRemainingDeck(int playerIndex) {
        return mPlayers[playerIndex].getRamainingDeck();
    }

    public CardSet getField(int playerIndex) {
        return mPlayers[playerIndex].getField();
    }

    public CardSet getGrave(int playerIndex) {
        return mPlayers[playerIndex].getGrave();
    }

    public int getPhase() {
        return mPhase;
    }

    public Sock getSock() {
        return mSock;
    }

    public void nextPhase() {
        mPhase = (mPhase == PHASE_TACTICS ? PHASE_BATTLE : PHASE_TACTICS);
        if (mPhase == PHASE_TACTICS) {
            isCardSet = false;
        }
    }

    public void send(String message) {
        if (isWatcher()) {
            if (message.startsWith("$CHAT:")) {
                message = "$WATCHCHAT:" + message.substring("$CHAT:".length());
            } else if (message.startsWith("$DISCONNECT:")) {
            } else if (message.startsWith("$WATCHERPING:")) {
            } else {
                return;
            }
        }

        mSock.send(mSock.getSocket(), message);
    }

    public Player getPlayer(int playerIndex) {
        return mPlayers[playerIndex];
    }

    public void setUITitle(String title) {
        mUI.setCusTitle(title);
    }

    public void insertMessage(String message, Color color) {
        mUI.insertMessage(message, color);
    }
}
